//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/buola.h>

#include <cerrno>
#include <unistd.h>
#include <execinfo.h>
#include <cstdio>
#include <ctime>

#include <buola/tty/output.h>
#include <buola/datetime/clocks.h>
#include <buola/datetime/cdatetime.h>

namespace buola {

static CMonotonicTime sTimer;

std::string c_error_string(int pErrno)
{
    char lError[1024];
#if BUOLA_PLATFORM_MAC
    strerror_r(pErrno,lError,1024);
    return lError;
#elif BUOLA_PLATFORM_WINDOWS
    strerror_s(lError,1024,pErrno);
    return lError;
#else
    char *lStr=strerror_r(pErrno,lError,1024);
    return lStr;
#endif
}

void back_trace()
{
    void *array[50];
    std::size_t size;
    char **strings;
    std::size_t i;

    size = backtrace (array, 50);
    strings = backtrace_symbols (array, size);

    gOut << "Obtained " << size << " stack frames.\n";
    for (i = 0; i < size; i++)
        gOut << strings[i] << "\n";
    free (strings);
}

void fatal_error(const char *pString)
{
    gErr << "FATAL ERROR: " << pString;
    back_trace();
    _exit(1);
}

void start_timer()
{
    sTimer=CMonotonicClock::now();
}

double get_timer(bool pReset)
{
    CMonotonicTime lNow=CMonotonicClock::now();
    double lReturn=to_double_seconds(sTimer-lNow);
    if(pReset)
        sTimer=lNow;
    return lReturn;
}

void end_timer()
{
    CMonotonicTime lNow=CMonotonicClock::now();
    msg_info() << tty::color(tty::COLOR_BRIGHTWHITE,"Time: ") << to_double_seconds(lNow-sTimer) << "\n";
}

void end_timer(const std::string &pLead)
{
    CMonotonicTime lNow=CMonotonicClock::now();
    msg_info() << tty::color(tty::COLOR_BRIGHTWHITE,pLead) << ": " << to_double_seconds(lNow-sTimer) << "\n";
}

void abs_timer(bool pSet)
{
    static CMonotonicTime lAbsTimer;

    if(pSet)
    {
        lAbsTimer=CMonotonicClock::now();
        return;
    }

    CMonotonicTime lNow=CMonotonicClock::now();
    double lSeconds=to_double_seconds(lNow-lAbsTimer);
    msg_info() << tty::color(tty::COLOR_BRIGHTWHITE,"AbsTime: ") << lSeconds << "\n";
}

void print_time()
{
    msg_info() << "time=" << CCalendarClock::now() << "\n";
}

io::CTextWriter &msg_error()
{
    gErr << tty::color(tty::COLOR_RED,"ERROR: ");
    return gErr;
}

io::CTextWriter &msg_warn()
{
    gErr << tty::color(tty::COLOR_YELLOW,"WarninG: ");
    return gErr;
}

/*namespace buola*/ }
